#include <math.h>
#include <stdlib.h>
#include <QtCore/QRegExp>
+
#include "defs.h"
#include "csv_util.h"
+#include "garmin_fs.h"
#include "grtcirc.h"
-#include "strptime.h"
#include "jeeps/gpsmath.h"
-#include "garmin_fs.h"
+#include "src/core/logging.h"
+#include "strptime.h"
#define MYNAME "CSV_UTIL"
/* usage: p = csv_stringclean(stringtoclean, "&,\"") */
/* (strip out ampersands, commas, and quotes. */
/*********************************************************************/
-// Implement the C version via Qt - the reverse of most of our shims.
-char*
-csv_stringclean(const char* source, const char* chararray)
-{
- /* Make a copy of the source... */
- QString cleansed(csv_stringclean(QString(source), chararray));
- return xstrdup(cleansed);
-}
-
QString
csv_stringclean(const QString& source, const QString& to_nuke)
{
xcsv_file.gps_datum = GPS_DATUM_WGS84;
}
+void validate_fieldmap(field_map_t* fmp, bool is_output) {
+ QString qkey = fmp->key;
+ QString qval = fmp->val;
+ QString qprintfc = fmp->printfc;
+
+ if (qkey.isEmpty()) {
+ Fatal() << MYNAME << ": xcsv style is missing" <<
+ (is_output ? "output" : "input") << "field type.";
+ }
+ if (!fmp->val) {
+ Fatal() << MYNAME << ": xcsv style" << qkey << "is missing default.";
+ }
+ if (is_output && !fmp->printfc) {
+ Fatal() << MYNAME << ": xcsv style" << qkey << "output is missing format specifier.";
+ }
+}
+
/*****************************************************************************/
/* xcsv_ifield_add() - add input field to ifield queue. */
/* usage: xcsv_ifield_add("DESCRIPTION", "", "%s") */
fmp->hashed_key = xm ? xm->xt_token : -1;
fmp->val = val;
fmp->printfc = pfc;
+ validate_fieldmap(fmp, false);
ENQUEUE_TAIL(&xcsv_file.ifield, &fmp->Q);
xcsv_file.ifield_ct++;
fmp->val = val;
fmp->printfc = pfc;
fmp->options = options;
+ validate_fieldmap(fmp, true);
ENQUEUE_TAIL(xcsv_file.ofield, &fmp->Q);
xcsv_file.ofield_ct++;
i = 0;
QUEUE_FOR_EACH(xcsv_file.ofield, elem, tmp) {
- char* obuff;
double lat = latitude;
double lon = longitude;
/*
anyname = wpt->notes;
}
if (anyname.isEmpty()) {
- anyname = xstrdup(fmp->val);
+ anyname = fmp->val;
}
buff = QString().sprintf(fmp->printfc, CSTR(anyname));
}
warning(MYNAME ": Unknown style directive: %s\n", fmp->key);
break;
}
- obuff = csv_stringclean(CSTR(buff), xcsv_file.badchars);
+ QString obuff = csv_stringclean(buff, xcsv_file.badchars);
if (field_is_unknown && fmp->options & OPTIONS_OPTIONAL) {
- goto next;
+ continue;
}
if (xcsv_file.field_encloser) {
* ""%s"" to smuggle bad characters through.
*/
if (0 == strcmp(fmp->printfc, "\"%s\"")) {
- gbfprintf(xcsv_file.xcsvfp, "\"%s\"", obuff);
- } else {
- gbfprintf(xcsv_file.xcsvfp, "%s", obuff);
+ obuff = '"' + obuff + '"';
}
+ gbfputs(obuff, xcsv_file.xcsvfp);
if (xcsv_file.field_encloser) {
/* print the enclosing character(s) */
gbfprintf(xcsv_file.xcsvfp, "%s", xcsv_file.field_encloser);
}
-
-next:
- xfree(obuff);
}
gbfprintf(xcsv_file.xcsvfp, "%s", xcsv_file.record_delimiter);
* gbfputs: (as fputs)
*/
-int
-gbfputs(const char* s, gbfile* file)
-{
- return gbfwrite(s, 1, strlen(s), file);
-}
-
// This is a depressing hack, meant to ease the pain from C strings
// to QStrings, which are consitently encoded.
int
* gbfputcstr: write a NULL terminated string into a stream (!) including NULL
* return the number of written characters
*/
-
int
-gbfputcstr(const char* s, gbfile* file)
+gbfputcstr(const QString& s, gbfile* file)
{
- int len;
-
- len = (s == NULL) ? 0 : strlen(s);
- if (len > 0) {
- return gbfwrite(s, 1, len + 1, file);
- } else {
- gbfputc(0, file);
- return 1;
- }
-}
-int
-gbfputcstr(const QString& s, gbfile* file)
-{
- return gbfputcstr(qPrintable(s), file);
+ QByteArray qs = s.toUtf8();
+ int rv = gbfwrite(qs.constData(), 1, qs.size(), file);
+ gbfputc(0, file);
+ return rv;
}
/*
* return the number of written characters
*/
-int
-gbfputpstr(const char* s, gbfile* file)
-{
- int len;
-
- len = (s == NULL) ? 0 : strlen(s);
- if (len > 255) {
- len = 255; /* the maximum size of a standard pascal string */
- }
- gbfputc(len, file);
- if (len > 0) {
- gbfwrite(s, 1, len, file);
- }
- return (len + 1);
-}
-
int
gbfputpstr(const QString& s, gbfile* file)
{
- const char* t = xstrdup(CSTR(s));
- int r = gbfputpstr(t, file);
- xfree(t);
- return r;
+ QString out(s);
+ // Pascal strings can be a max of 255 bytes.
+ out.truncate(255);
+
+ gbfputc(out.size(), file);
+ QByteArray qs = s.toUtf8();
+ int rv = gbfwrite(qs.constData(), 1, qs.size(), file);
+ return rv;
}
/* Much more higher level functions */
int gbvfprintf(gbfile* file, const char* format, va_list ap);
int gbfprintf(gbfile* file, const char* format, ...);
int gbfputc(int c, gbfile* file);
-int gbfputs(const char* s, gbfile* file);
int gbfputs(const QString& s, gbfile* file);
int gbfwrite(const void* buf, const gbsize_t size, const gbsize_t members, gbfile* file);
int gbfflush(gbfile* file);
int gbfputdbl(const double d, gbfile* file); // write a double value
int gbfputflt(const float f, gbfile* file); // write a float value
-int gbfputcstr(const char* s, gbfile* file); // write string including '\0'
int gbfputcstr(const QString& s, gbfile* file); // write string including '\0'
-int gbfputpstr(const char* s, gbfile* file); // write as pascal string
int gbfputpstr(const QString& s, gbfile* file); // write as pascal string
gbsize_t gbfcopyfrom(gbfile* file, gbfile* src, gbsize_t count);